package xtoken

import (
	"errors"
	"gitee.com/xiedongji/antgo/cpts/xcfg"
	"github.com/golang-jwt/jwt/v4"
	"time"
)

/* ====================================================================== *
 * 功能：加密解密 token
 * 描述：用于 WEB 接口鉴权
 * ====================================================================== */
type SessionInfo struct {
	UserId    int64     `json:"user_id"`
	Uuid      string    `json:"uuid"`
	UserName  string    `json:"user_name"`
	LoginTime time.Time `json:"login_time"`
}

type myClaims struct {
	Info                 *SessionInfo // 未加密信息
	jwt.RegisteredClaims              // 注意!这是jwt-go的v4版本新增的,原先是jwt.StandardClaims
}

// ========= 生成Token ============
func GenToken(sessionInfo *SessionInfo) (string, error) {
	claims := &myClaims{
		Info: sessionInfo,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour * time.Duration(1))), // 过期时间3小时
			IssuedAt:  jwt.NewNumericDate(time.Now()),                                        // 签发时间
			NotBefore: jwt.NewNumericDate(time.Now()),                                        // 生效时间
		},
	}
	// 生成Token,指定签名算法和claims
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // 使用HS256算法
	// 签名
	tokenString, err := token.SignedString([]byte(xcfg.GetString("jwt.secret_key")))
	return tokenString, err
}

// ============ 解析 token =============
func ParseToken(tokenStr string) (*SessionInfo, error) {
	token, err := jwt.ParseWithClaims(tokenStr, &myClaims{}, secret())
	if err != nil {
		if ve, ok := err.(*jwt.ValidationError); ok {
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, errors.New("token 格式不正确")
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				return nil, errors.New("token 过期")
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, errors.New("token not active yet")
			} else {
				return nil, errors.New("token 未知错误")
			}
		}
	}
	if claims, ok := token.Claims.(*myClaims); ok && token.Valid {
		return claims.Info, nil
	}

	return nil, errors.New("token 未知错误1")
}

func secret() jwt.Keyfunc {
	return func(token *jwt.Token) (interface{}, error) {
		return []byte(xcfg.GetString("jwt.secret_key")), nil // 这是我的secret
	}
}
